package com.lagou.rpc.consumer.proxy;

import com.alibaba.fastjson.JSON;
import com.lagou.rpc.common.RpcRequest;
import com.lagou.rpc.common.RpcResponse;
import com.lagou.rpc.consumer.client.RpcClient;

import java.lang.reflect.Proxy;
import java.util.*;

/**
 * 客户端代理类-创建代理对象
 * 1.封装request请求对象
 * 2.创建RpcClient对象
 * 3.发送消息
 * 4.返回结果
 *
 * @author user
 */
public class RpcClientProxy {

    private static final Map<String, RpcClient> CLIENT_MAP = new HashMap<>();

    public static void addClient(String ip, int port) throws Exception {
        RpcClient client = new RpcClient(ip, port);
        CLIENT_MAP.put(ip + "-" + port, client);
        System.out.println(ip + "-" + port + " 上线");
    }

    public static void removeClient(String ip, int port) {
        RpcClient rpcClient = CLIENT_MAP.remove(ip + "-" + port);
        if (rpcClient == null) {
            return;
        }
        System.out.println(ip + "-" + port + " 下线");
        rpcClient.close();
    }

    public static List<RpcClient> listRpcClient() {
        return new ArrayList<>(CLIENT_MAP.values());
    }


    private static RpcClient getRpcClient() {
        List<RpcClient> values = new ArrayList<>(CLIENT_MAP.values());
        if (values.isEmpty()) {
            return null;
        }
        int index = (int) (Math.random() * values.size());
        return values.get(index);
    }

    public static Object createProxy(Class serviceClass) {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{serviceClass}, (proxy, method, args) -> {
            //1.封装request请求对象
            RpcRequest rpcRequest = new RpcRequest();
            rpcRequest.setRequestId(UUID.randomUUID().toString());
            rpcRequest.setClassName(method.getDeclaringClass().getName());
            rpcRequest.setMethodName(method.getName());
            rpcRequest.setParameterTypes(method.getParameterTypes());
            rpcRequest.setParameters(args);
            RpcClient rpcClient = null;
            long startTime = System.currentTimeMillis();
            //2.创建RpcClient对象
            rpcClient = getRpcClient();
            if (rpcClient == null) {
                throw new RuntimeException("没有可用的服务");
            }
            //3.发送消息
            Object responseMsg = rpcClient.send(JSON.toJSONString(rpcRequest));
            RpcResponse rpcResponse = JSON.parseObject(responseMsg.toString(), RpcResponse.class);
            if (rpcResponse.getError() != null) {
                throw new RuntimeException(rpcResponse.getError());
            }
            //4.返回结果
            Object result = rpcResponse.getResult();
            long endTime = System.currentTimeMillis();
            rpcClient.responseTime(startTime, endTime - startTime);
            return JSON.parseObject(result.toString(), method.getReturnType());
        });
    }
}
